package session.stateless.SCM;

import entity.SCM.MaterialLine;
import entity.SCM.MaterialOrder;
import entity.SCM.MaterialRequest;
import entity.SCM.MaterialRequestTemp;
import entity.RawMaterial;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@Stateless
public class MaterialRequestBean implements MaterialRequestBeanLocal {
    
    private List<MaterialRequestTemp> materialRequestList;
    @PersistenceContext()
    EntityManager em;
    DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
    
    private MaterialRequestTemp createMRT(MaterialRequest mr){
        Date date = new Date();
        MaterialRequestTemp mrt = new MaterialRequestTemp();
        mrt.setCurrentDate(dateFormat.format(date));
        List<MaterialLine> mlList = new ArrayList<MaterialLine>();
        for(MaterialLine ml:mr.getMaterialLines()){
            mlList.add(this.createMaterialLine(ml.getRawMaterial().getMaterialType(), ml.getQuantity()));
        }
        mrt.setMaterialLines(mlList);
        mrt.setMaterialRequest(mr);
        em.persist(mrt);
        em.flush();
        return mrt;
    }
    
    @Override
    public boolean statePendingToArrived(Long id){
        boolean change = false;
        MaterialRequest mr = em.find(MaterialRequest.class, id);
        if(mr!=null){
            mr.setRequestState(MaterialRequest.State.Arrived);
            change = true;
        }
        return change;
    }
    
    @Override
    public List<MaterialRequestTemp> getMaterialRequestNeedProcess(){
        List<MaterialRequest> mrList = this.getPendingMaterialRequest();
        for(MaterialRequest mr: mrList){
            createMRT(mr);
            mr.setRequestState(MaterialRequest.State.Processed);
        }
        Query q = em.createQuery("SELECT c FROM MaterialRequestTemp c");
        List<MaterialRequestTemp> temp = q.getResultList();
        materialRequestList = new ArrayList<MaterialRequestTemp>();
        for(MaterialRequestTemp mrt:temp){
            if(mrt.getMaterialLines()==null || mrt.getMaterialLines().isEmpty()){                
                System.out.print("Get material request need process----------");
            }else{
                materialRequestList.add(mrt);
            }
        }
        return materialRequestList;
    }
    
    @Override
    public void removeMaterialLines(MaterialRequestTemp mr, List<MaterialLine> mls){
        List<MaterialLine> mrl = mr.getMaterialLines();
        for(MaterialLine ml:mls){
            mrl.remove(ml);
        }
        em.flush();
    }
    
    @Override
    public Long createMaterialRequest(List<MaterialLine> materialLines) {
        
        Date date = new Date();
        
        MaterialRequest materialRequest = new MaterialRequest();
        
        materialRequest.setRequestState(MaterialRequest.State.Pending);
        materialRequest.setCurrentDate(dateFormat.format(date));
        materialRequest.setMaterialLines(materialLines);
        
        em.persist(materialRequest);
        em.flush();
        
        return materialRequest.getMaterialRequestId();
    }

    @Override
    public MaterialLine createMaterialLine(String materialType, Long quantity) {
        
        MaterialLine materialLine = new MaterialLine();
        RawMaterial rawMaterial = em.find(RawMaterial.class, materialType);
        if(rawMaterial == null){
            System.out.println("The Raw Material Does Not Exist!");
            return null;
        }
        materialLine.setRawMaterial(rawMaterial);
        materialLine.setQuantity(quantity);
        em.persist(materialLine);
        em.flush();
        
        return materialLine;
    }

    @Override
    public boolean processPendingMaterialRequest(Long requestId) {
        
        MaterialRequest materialRequest = em.find(MaterialRequest.class, requestId);
        
        if(materialRequest == null){
            System.out.println("This Material Request Does Not Exist!");
            return false;
        }
        else if(materialRequest.getRequestState().equals(MaterialRequest.State.Pending)){
            materialRequest.setRequestState(MaterialRequest.State.Processed);
            em.flush();
            
            return true;
        }
        else{
            System.out.println("Error Occurs @ MaterialRequestBean::peocessPendingMaterialRequest()");
            return false;
        }
    }

    @Override
    public boolean processArrivedMaterialRequest(Long requestId) {
        
        MaterialRequest materialRequest = em.find(MaterialRequest.class, requestId);
        
        if(materialRequest == null){
            System.out.println("This Material Request Does Not Exist!");
            return false;
        }
        else if(materialRequest.getRequestState().equals(MaterialRequest.State.Arrived)){
            materialRequest.setRequestState(MaterialRequest.State.Successful);
            em.flush();
            
            return true;
        }
        else{
            System.out.println("Error Occurs @ MaterialRequestBean::peocessProcessMaterialRequest()");
            return false;
        }
    }

    @Override
    public List<MaterialRequest> getMaterialRequest() {
        
        Query q = em.createQuery("SELECT c FROM MaterialRequest c WHERE c.requestState = :requestState1 OR c.requestState = :requestState2 OR c.requestState = :requestState3 OR c.requestState = :requestState4");
        q.setParameter("requestState1", MaterialRequest.State.Pending);
        q.setParameter("requestState2", MaterialRequest.State.Processed);
        q.setParameter("requestState3", MaterialRequest.State.Successful);
        q.setParameter("requestState4", MaterialRequest.State.Arrived);
        
        return q.getResultList();
    }
    
    @Override
    public List<MaterialRequest> getArriveMaterialRequest() {
        
        Query q = em.createQuery("SELECT c FROM MaterialRequest c WHERE c.requestState = :requestState");
        q.setParameter("requestState", MaterialRequest.State.Arrived);
        
        return q.getResultList();
    }

    @Override
    public List<MaterialRequest> getPendingMaterialRequest() {
        
        Query q = em.createQuery("SELECT c FROM MaterialRequest c WHERE c.requestState = :requestState");
        q.setParameter("requestState", MaterialRequest.State.Pending);
        
        return q.getResultList();
    }

    @Override
    public List<MaterialRequest> getProcessMaterialRequest() {
        
        Query q = em.createQuery("SELECT c FROM MaterialRequest c WHERE c.requestState = :requestState");
        q.setParameter("requestState", MaterialRequest.State.Processed);
        
        return q.getResultList();
    }
    
    @Override
    public List<MaterialRequest> getSuccessMaterialRequest() {
        
        Query q = em.createQuery("SELECT c FROM MaterialRequest c WHERE c.requestState = :requestState");
        q.setParameter("requestState", MaterialRequest.State.Successful);
        
        return q.getResultList();
    }
   
    @Override
    public boolean checkMaterialRequest(MaterialRequest mr){
        List<MaterialOrder> mol = mr.getMaterialOrders();
        if(mol.isEmpty()||mol==null){
            return false;
        }else{
            if( mol.get(0).getMaterialRequestTemp().getMaterialLines().isEmpty() ||
                    mol.get(0).getMaterialRequestTemp().getMaterialLines()==null){
                for(MaterialOrder mo: mol){
                    if(mo.getMaterialOrderState().equals(MaterialOrder.State.Sent) 
                            || mo.getMaterialOrderState().equals(MaterialOrder.State.Pending) ){
                        return false;
                    }
                }
                return true;
            }else{
                return false;
            }
        }
    }
}
